/**
 * @file       main.c
 * @author     mz8023yt
 * @email      mz8023yt@163.com
 * @version    V1.0
 * @date       2022-03-13
 * @brief      st7735 lcd test
 */

#include "driver/gpio.h"
#include "driver/spi_master.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "img1.c"
#include "img2.c"
#include "img3.c"
#include "logo.c"
#include "st7735.h"
#include <stdio.h>
#include <string.h>
#include <unistd.h>

#define ST7735_CLK_PIN  2
#define ST7735_MOSI_PIN 3
#define ST7735_RST_PIN  10
#define ST7735_DC_PIN   6
#define ST7735_CS_PIN   7
#define ST7735_BL_PIN   11

static spi_device_handle_t spi;

void esp32c3_spi_write(uint8_t* bytes, uint32_t len)
{
	uint32_t section = 4096;
	spi_transaction_t t;

	if (!len) {
		return;
	}

	while (len > section) {
		memset(&t, 0, sizeof(t));             // Zero out the transaction
		t.length = 8 * section;               // Command is 8 bits
		t.tx_buffer = bytes;                  // The data is the cmd itself
		spi_device_polling_transmit(spi, &t); // Transmit!
		bytes += section;
		len -= section;
	}

	memset(&t, 0, sizeof(t));             // Zero out the transaction
	t.length = 8 * len;                   // Command is 8 bits
	t.tx_buffer = bytes;                  // The data is the cmd itself
	spi_device_polling_transmit(spi, &t); // Transmit!
}

void esp32c3_rst_pin(int val)
{
	gpio_set_level(ST7735_RST_PIN, val);
}

void esp32c3_dc_pin(int val)
{
	gpio_set_level(ST7735_DC_PIN, val);
}

void esp32c3_bl_pin(int val)
{
	gpio_set_level(ST7735_BL_PIN, val);
}

void esp32c3_msleep(int ms)
{
	usleep(1000 * ms);
}

void board_init()
{
	/* gpio */
	gpio_reset_pin(ST7735_RST_PIN);
	gpio_set_direction(ST7735_RST_PIN, GPIO_MODE_OUTPUT);

	gpio_reset_pin(ST7735_DC_PIN);
	gpio_set_direction(ST7735_DC_PIN, GPIO_MODE_OUTPUT);

	gpio_reset_pin(ST7735_BL_PIN);
	gpio_set_direction(ST7735_BL_PIN, GPIO_MODE_OUTPUT);

	spi_bus_config_t buscfg = {
		.miso_io_num = -1,
		.mosi_io_num = ST7735_MOSI_PIN,
		.sclk_io_num = ST7735_CLK_PIN,
		.quadwp_io_num = -1,
		.quadhd_io_num = -1,
		.max_transfer_sz = 4096,
	};

	spi_device_interface_config_t devcfg = {
		.clock_speed_hz = 60000000,    // SPI Clock
		.mode = 0,                     // SPI mode
		.spics_io_num = ST7735_CS_PIN, // CS pin
		.queue_size = 7,               // We want to be able to queue 7 transactions at a time
	};

	spi_bus_initialize(SPI2_HOST, &buscfg, SPI_DMA_CH_AUTO);
	spi_bus_add_device(SPI2_HOST, &devcfg, &spi);
}

void app_main(void)
{
	int i = 0;
	int j = 0;
	int w = 0;
	int h = 0;
	int x = 0;
	int y = 0;
	struct st7735 lcd;
	uint8_t* buf = NULL;

	board_init();

	/* set lcd param */
	lcd.cfg.fix.width = 128;
	lcd.cfg.fix.height = 160;
	lcd.cfg.fix.xshift = 0;
	lcd.cfg.fix.yshift = 0;
	lcd.cfg.var.orien = 0;
	w = lcd.cfg.fix.width;
	h = lcd.cfg.fix.height;

	/* register the operation */
	lcd.ops.pin.rst = esp32c3_rst_pin;
	lcd.ops.pin.dc = esp32c3_dc_pin;
	lcd.ops.pin.bl = esp32c3_bl_pin;
	lcd.ops.time.msleep = esp32c3_msleep;
	lcd.ops.spi.write = esp32c3_spi_write;
	st7735_init(&lcd);

	/* 测试矩形填充函数色彩，全屏显示白色 */
	st7735_rect_fill_color(&lcd, 0, 0, w - 1, h - 1, RGB565_WHITE);

	/* 测试矩形填充函数，居中显示非全屏图片 */
	x = w / 2 - 20;
	y = h / 2 - 20;
	buf = gImage_logo;
	st7735_rect_fill(&lcd, x, y, x + 39, y + 39, (uint16_t*)buf);

	/* 测试画点函数，最下方绘制屏幕40行的红色色块 */
	for (j = h - 40; j < h; j++) {
		for (i = 0; i < w; i++) {
			st7735_point_draw(&lcd, i, j, RGB565_RED);
		}
	}
	vTaskDelay(500 / portTICK_PERIOD_MS);

	/* 测试矩形填充函数，显示全屏图片 */
	while (1) {
		buf = gImage_1;
		st7735_rect_fill(&lcd, 0, 0, w - 1, h - 1, (uint16_t*)buf);
		vTaskDelay(500 / portTICK_PERIOD_MS);
		printf("OK1\n");

		buf = gImage_2;
		st7735_rect_fill(&lcd, 0, 0, w - 1, h - 1, (uint16_t*)buf);
		vTaskDelay(500 / portTICK_PERIOD_MS);
		printf("OK2\n");

		buf = gImage_3;
		st7735_rect_fill(&lcd, 0, 0, w - 1, h - 1, (uint16_t*)buf);
		vTaskDelay(500 / portTICK_PERIOD_MS);
		printf("OK3\n");
	}
}
